﻿#!/usr/bin/env python
# -*- coding: utf-8 -*-
# KonomeBot developed by Farseerfc,irolar
#if you would like to join in the develop, please twitter @irolar
#req_handler, handling any user query service


from __future__ import division
from math import *
import random
import urllib,urllib2
import pickle
from db_entity import User ,Jid

class KonoCmd:
    ''' Base class of a command '''
    def __init__(self,message,args,lang='chs'):
        '''
        constructor, using a message object to construct. args is the given message split by space
        '''
        self.message = message
        self.args = args
        self.leftargs=args[1:]
        self.numleftargs=len(args)-1
        self.lang=lang
        self.user = User(Jid(self.message.sender))
    def getdata(self,queryurl,list,separate='',querysuffix='',code='utf8'):
        reqlist=separate.join(list)
        querysuffix=querysuffix
        info=urllib2.urlopen(queryurl+reqlist+querysuffix)
        temp=info.readlines()
        if not code=='utf8':
            temp=[i.decode(code).encode('utf8') for i in temp]
        if len(temp)==1:
            temp=temp[0]
        return temp
    def do_reply(self):
        ''' virtual fucntion, to be overrided in sub-classes '''
        return 'KonoCmd Reply!'
    def reply(self):
        ''' get the reply using do_reply '''
        self.user.add_history(self.message.body)
        self.message.reply(self.do_reply())

class Cmd_c(KonoCmd):
    '''
    Calc the given expression
    支持简单计算,可以精确处理除法。
    '''
    def do_reply(self):
        return str(eval(' '.join(self.leftargs) ) )

class Cmd_hello(KonoCmd):
    '''
    Show a hello message
    '''
    Hello=['Hello你妹啊，你个死妹控','Hi,Hi，Hi你妹啊，你个死妹控','主人，欢迎回来～～','你下辈子也是CJ的魔法师哦～～','都，都说了这么多了还不明白吗。你是，笨、笨、笨……那个，果然这种说法不太……啊……大、大笨蛋对吧！','╮(╯▽╰)╭','不要看，見ないで','おはよう不在反馈内诶','H是不对的','エッチなことはダメ','エッチなことは大嫌いわ','H什么的……不要嘛……']
    def do_reply(self):
        return random.choice(self.Hello)
class Cmd_h(Cmd_hello):
    Hello=['H是不对的','エッチなことはダメ','エッチなことは大嫌いわ','H什么的……不要嘛……']
    pass
class Cmd_hi(Cmd_hello):
    pass
class Cmd_help(KonoCmd):
    '''
    Show the command list
    '''
    def do_reply(self):
        cmd_list = [ class_name[4:]                     # omit 'Cmd_' head
            for class_name in globals()                 # get all class names that
            if class_name.startswith('Cmd_')]       # started with 'Cmd_'
        result = []
        if self.numleftargs >= 1:
             cmd_name = self.leftargs[0].lower()
             return '%s:\t%s' % (cmd_name, globals()['Cmd_'+cmd_name].__doc__)
        for cmd_name in cmd_list:
            doc =  globals()['Cmd_'+cmd_name].__doc__
            if (doc != None) and (len(doc.split('\n')) > 1) :
                doc = doc.split('\n')[1]							# get the second line of doc
            result.append('%s:\t%s' % (cmd_name, doc))
        return '\n'.join(result)

class Cmd_ml(KonoCmd):
    '''
    Query the Mobilephone number Location
    查询手机归属地
    格式:ml 手机号码
    '''
    def do_reply(self):
        qresult=self.getdata('http://api.showji.com/locating/?m=',self.leftargs[0],'','&output=text')
        result=''.join(qresult)
        return result

class Cmd_roe(KonoCmd):
    '''
    Rate Of Exchange qury, 汇率查询
    只提供一个参数时表示100元人民币可兑换多少[参数1]外币,
    格式:roe 日元/jpy
    只提供两个参数时表示[参数2]元这种[参数1]外币将兑换成多少人民币
    格式:roe 日元/jpy 10000
    提供三个参数时表示[参数3]元这种[参数1]外币将兑换成多少[参数2]的外币
    格式:roe 日元/jpy 加拿大/cad 10000
    可以输入三个字母的货币代号查询,也可以使用国家名查询,除了欧元,美元等极少数币种外,请使用国家名查询
    '''
    Currencies={'ars': ['Argentine Peso', 'Argentina', '阿根廷', 'ars'], 'ron': ['New Romanian Leu', 'Romania', '罗马', 'ron'], 'myr': ['Malasian Ringgit', 'Malasia', '马来西亚', 'myr'], 'inr': ['Indian Rupee', 'India', '印度', 'inr'], 'svc': ['Salvadoran colon', 'El Salvador', '圣萨尔瓦多', 'svc'], 'jpy': ['Japanese Yen', 'Japan', '日元', 'jpy'], 'czk': ['Czech Koruna', 'Czech Republic', '捷克', 'czk'], 'brl': ['Brazilian Real', 'Brazil', '巴西', 'brl'], 'sar': ['Saudi Arabian Riyal', 'Saudi Arabia', '沙特阿拉伯', 'sar'], 'zar': ['South African Rand', 'South Africa', '南非', 'zar'], 'sgd': ['Singapore Dollar', 'Singapore', '新加坡', 'sgd'], 'try': ['New Turkish Lira', 'Turcode', '土耳其', 'try'], 'usd': ['United States Dollar', 'United States', '美元', 'usd'], 'aud': ['Australian Dollar', 'Australia', '澳大利亚', 'aud'], 'twd': ['Taiwan Dollar', 'Taiwan', '新台币', 'twd'], 'qar': ['Qatari Riyal', 'Qatar', '卡塔尔', 'qar'], 'sek': ['Swedish Krona', 'Sweden', '瑞典', 'sek'], 'cny': ['Chinese Yuan', 'China', '人民币', 'cny'], 'veb': ['Venezuelan Bolivar', 'Venezuela', '委内瑞拉', 'veb'], 'jmd': ['Jamaican Dollar', 'Jamaica', '牙买加', 'jmd'], 'hrk': ['Croatian Kuna', 'Croatia', '克罗地亚', 'hrk'], 'lkr': ['Sri Lanka Rupee', 'Sri Lanka', '斯里兰卡', 'lkr'], 'skk': ['Slovak Koruna', 'Slovakia', '斯洛文尼亚', 'skk'], 'eur': ['Euro', 'European Union', '欧元', 'eur'], 'huf': ['Hungarian Forint', 'Hungary', '匈牙利', 'huf'], 'eek': ['Estonian Kroon', 'Estonia', '爱沙尼亚', 'eek'], 'nok': ['Norwegian Krone', 'Norway', '挪威', 'nok'], 'rub': ['Russian Rouble', 'Russia', '俄罗斯', 'rub'], 'hnl': ['Honduran Lempira', 'Honduras', '洪都拉斯', 'hnl'], 'mxn': ['Mexican Peso', 'Mexico', '墨西哥', 'mxn'], 'mad': ['Moroccan Dirham', 'Morocco', '摩洛哥', 'mad'], 'pln': ['Polish Zloty', 'Poland', '波兰', 'pln'], 'php': ['Philippine Peso', 'Philippines', '菲律宾', 'php'], 'hkd': ['Hong Kong Dollar', 'Hong Kong', '港币', 'hkd'], 'pyg': ['Paraguay Guarani', 'Paraguay', '巴拉圭', 'pyg'], 'cop': ['Colombian Peso', 'Colombia', '哥伦比亚', 'cop'], 'chf': ['Swiss Franc', 'Switzerland', '瑞士', 'chf'], 'clp': ['Chilean Peso', 'Chile', '智利', 'clp'], 'krw': ['Korea Won', 'Korea', '韩元', 'krw'], 'bgn': ['Bulgarian Lev', 'Bulgaria', '保加利亚', 'bgn'], 'dkk': ['Danish Krone', 'Denmark', '丹麦', 'dkk'], 'isk': ['Icelandic Krona', 'Iceland', '冰岛', 'isk'], 'tnd': ['Tunisian Dinar', 'Tunisia', '突尼斯', 'tnd'], 'gbp': ['Pound Sterling', 'United Kingdom', '英镑', 'gbp'], 'nzd': ['New Zealand Dollar', 'New Zealand', '新西兰', 'nzd'], 'lvl': ['Latvian Lats', 'Latvia', '拉脱维亚', 'lvl'], 'ltl': ['Lithuanian Litas', 'Lithuania', '黎巴嫩', 'ltl'], 'thb': ['Thai Baht', 'Thailand', '泰国', 'thb'], 'cad': ['Canadian Dollar', 'Canada', '加拿大', 'cad']}

    def findcurrency(self,currency):
        currency=currency
        if self.Currencies.has_key(currency):
            return currency
        else:
            for key in self.Currencies:
                if currency in self.Currencies[key]:
                    return key
                else :
                    pass
    '''
    def getdata(self):
        if self.numleftargs==1:
            cm2=self.findcurrency(self.leftargs[0])
            cm1='cny'
            cm3='100'
        elif self.numleftargs==2:
            cm1=self.findcurrency(self.leftargs[0])
            cm2='cny'
            cm3=self.leftargs[1]
        elif self.numleftargs==3:
            cm1=self.findcurrency(self.leftargs[0])
            cm2=self.findcurrency(self.leftargs[1])
            cm3=self.leftargs[2]
        roelist=[cm1,cm2,str(cm3)]
        qresult=self.getdata('http://xurrency.com/api/',roelist,'/')
        temp = eval(qresult)
        if temp['status']=='ok':
            return [cm3,self.Currencies[cm1][-2],temp['result']['value'],self.Currencies[cm2][-2]]         #将很容易进行语言上的扩展。
        else:
            return temp['message']
    '''
    def getdata2(self):
        if self.numleftargs==1:
            cm2=self.findcurrency(self.leftargs[0])
            cm1='cny'
            cm3='100'
        elif self.numleftargs==2:
            cm1=self.findcurrency(self.leftargs[0])
            cm2='cny'
            cm3=self.leftargs[1]
        elif self.numleftargs==3:
            cm1=self.findcurrency(self.leftargs[0])
            cm2=self.findcurrency(self.leftargs[1])
            cm3=self.leftargs[2]
        else:
            pass
        roelist=[cm1.upper(),cm2.upper()]
        roequerysuffix='&count='+str(cm3)
        qresult=self.getdata('http://api.liqwei.com/currency/?exchange=',roelist,'|',roequerysuffix)
        return [cm3,self.Currencies[cm1][-2],qresult,self.Currencies[cm2][-2]]         #将很容易进行语言上的扩展。
    def do_reply(self):
        verment=self.getdata2()
        if len(verment)==4:
            result='当前%s%s可兑换 %s%s' %(verment[0],verment[1],verment[2],verment[3])
        else:
            result=verment
        return result

class Cmd_s(KonoCmd):
    '''
    STock 股票及指数查询
    不提供参数时显示沪深股市指数
    提供一个股票代码时显示单只股票的详细情况
    提供多个股票代码时显示多只股票的价格及涨跌情况以及沪深股市指数简略。
    格式:st
         st 600485(sh600485)
         st 600485 600486
    '''
    queue1=[8,10,12,14,16,18,20,22,24,26,28]         #显示单个股票队列
    queue2=[0,3,-1]
    queue3=[0,1,3]
    StockName=['股票名称','今日开盘价','昨日收盘价','当前价格','今日最高价','今日最低价','竞买价','竞卖价','成交量(手)','成交金额','买一手数','买一报价','买二手数','买二报价','买三手数','买三报价','买四手数','买四报价','买五手数','买五报价','卖一手数','卖一报价','卖二手数','卖二报价','卖三手数','卖三报价','卖四手数','卖四报价','卖五手数','卖五报价','日期','时间','涨幅']
    IndexName=['指数名称','当前点数','当前价格','涨跌率','成交量(手)','成交额(万元)']
    IndexList=['s_sh000001','s_sz399001']   #上证综合指数,深圳成份指数
    fcode=file('stockcode.txt','rb')
    stockcode=pickle.load(fcode)
    def changeargs(self,list):
        temp=[]
        if list==[]:
            if self.user.get_stock_count()!=0:
                temp=self.user.get_stockpure()
            else:
                pass
        else:
            for i in list:
                if i[0]=='s':
                    temp.append(i)
                elif i.isdigit():
                    if i[0] in ['5','6','9']:         #沪市A股
                        temp.append('sh'+i)
                    elif i[0] in ['0','2','3','7','8']:       #深市A股
                        temp.append('sz'+i)
                else:
                    for key in self.stockcode:
                        if i in key:
                            temp.append(key[-1])
        return temp
    def getdata2(self,list):
        list=list
        queryurl ='http://hq.sinajs.cn/list='
        reqlist=','.join(list)
        info = urllib2.urlopen(queryurl+reqlist)
        tempgot = info.readlines()
        temp = [i[i.find('"')+1:i.rfind('"')].decode('GBK').encode('utf-8') for i in tempgot]
        verment = [temp[i].split(',') for i in range(len(list))]
        return verment
    def processStock(self):
        verment=self.getdata2(self.leftargs)
        for i in range(len(self.leftargs)):
            for z in range(len(verment[i][1:-2])):
                verment[i][z+1]=float(verment[i][z+1])
            verment[i].append('%.2f%s' %(((verment[i][3])/(verment[i][2])-1)*100,'%'))
            for z in self.queue1:
                verment[i][z]=verment[i][z]/100
        return verment
    def processIndex(self):
        verment =self.getdata2(self.IndexList)
        for i in range(len(self.IndexList)):
            verment[i][3]='%.2f%s' %(float(verment[i][3]),'%')
        return verment
    def do_reply(self):
        self.leftargs=self.changeargs(self.leftargs)
        if len(self.leftargs) == 0:
            findex = self.processIndex()
            result = []
            for i in range(len(self.IndexList)):
                for z in range(len(self.IndexName)):
                    result.append( '%s %s' %(self.IndexName[z],findex[i][z]))
            return '\n'.join(result)
        elif len(self.leftargs) == 1:
            fstock = self.processStock()
            result = []
            for i in range(len(self.StockName)):
                result.append( '%s %s' %(self.StockName[i],fstock[0][i]))
            return '\n'.join(result)
        elif len(self.leftargs) >1:
            fstock = self.processStock()
            findex = self.processIndex()
            result = []
            for i in range(len(self.leftargs)):
                for z in self.queue2:
                    result.append( '%s %s' %(self.StockName[z],fstock[i][z]))
            for i in range(len(self.IndexList)):
                for z in self.queue3:
                    result.append( '%s %s' %(self.IndexName[z],findex[i][z]))
            return '\n'.join(result)

class Cmd_version(KonoCmd):
    '''
    Show the version of Konobot
    格式:version
    '''
    def do_reply(self):
        return '0.1.8'

class Cmd_whoami(KonoCmd):
    '''
    Display user information
    格式:whoami
    '''
    def do_reply(self):
        user = self.user.db
        return 'name %s, jid %s, reg_ts %s, last_ts %s, history %d' % (
            user.name,user.jid,user.reg_ts,user.last_ts,self.user.get_history_count())

class Cmd_history(KonoCmd):
    '''
    get command history of current user
    格式:history         : show all history
         history clear   : clear history
         history *index*   : show history with given index
    '''
    def do_reply(self):
        if self.numleftargs >= 1:
            if self.leftargs[0] == 'clear':
                count = self.user.get_history_count()
                self.user.clear_history()
                return 'History %d items cleared' % count
            elif self.leftargs[0].isdigit():
                index = int(self.leftargs[0] )
                his = self.user.get_history_by_index(index)
                return his.cmd
        result = self.user.get_history()
        return '\n'.join('[%s]%s:%s' % (his.ts,str(his.index),his.cmd) for his in result )
class Cmd_setup(Cmd_s):
    '''
    get command stock of current user
    格式:stock         : show all stock
         stock clear   : clear stock
         stock *index*   : show stock with given index
    '''
    def do_reply(self):
        if self.numleftargs >= 1:
            if self.leftargs[0] == 'clear':
                count = self.user.get_stock_count()
                self.user.clear_stock()
                return 'stock %d items cleared' % count
            else:
                self.leftargs=self.changeargs(self.leftargs)
                for i in self.leftargs:
                    if i not in self.user.get_stockpure():
                        self.user.add_stock(i.decode('utf8'))
        result = self.user.get_stock()
        return u'添加到股票列表\n'+'\n'.join('%s:%s' % (str(sto.index),sto.stock) for sto in result )